package com.plan.service.card.impl;

import com.plan.base.constant.BaseCode;
import com.plan.base.entity.Result;
import com.plan.controller.card.request.BaseReq;
import com.plan.controller.card.request.MyAwardPageListReq;
import com.plan.controller.card.request.SavePrizeDrawResultReq;
import com.plan.controller.card.request.UpdateLotteryRateReq;
import com.plan.controller.card.response.AwardProductListRes;
import com.plan.controller.card.response.PrizeDrawRes;
import com.plan.controller.user.response.UserVO;
import com.plan.dao.mapper.card.PrizeDrawLogMapper;
import com.plan.dao.service.card.AwardDaoService;
import com.plan.dao.service.card.CardDaoService;
import com.plan.dao.service.card.PointPrizeDrawSettingDaoService;
import com.plan.entity.card.AwardProduct;
import com.plan.entity.card.Card;
import com.plan.entity.card.PointLog;
import com.plan.entity.card.PointPrizeDrawSetting;
import com.plan.entity.card.PrizeDrawLog;
import com.plan.enums.DelFlagEnum;
import com.plan.enums.PointTypeEnum;
import com.plan.service.card.AwardService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

@Service
public class AwardServiceImpl implements AwardService {
    @Resource
    private AwardDaoService awardDaoService;
    @Resource
    private CardDaoService cardDaoService;
    @Resource
    private PointPrizeDrawSettingDaoService pointPrizeDrawSettingDaoService;
    @Resource
    private PrizeDrawLogMapper prizeDrawLogMapper;

    @Override
    public Result<Long> insert(AwardProduct product) {
        Integer existRate = awardDaoService.getExistRateByTeamId(product.getTeamId());
        if (existRate != null) {
            if (existRate + product.getRate() > 100) {
                return Result.fail(BaseCode.RATE_LIMIT);
            }
        }
        awardDaoService.insert(product);
        return Result.ok(product.getId());
    }

    @Override
    public Result<Long> update(AwardProduct product) {
        Integer existRate = awardDaoService.getExistRateByTeamId(product.getTeamId());
        AwardProduct old = awardDaoService.selectOneById(product.getTeamId(), product.getId());
        if (existRate - old.getRate() + product.getRate() > 100) {
            return Result.fail(BaseCode.RATE_LIMIT);
        }
        awardDaoService.update(product);
        return Result.ok(product.getId());
    }

    @Override
    public void delete(Long teamId, Long productId) {
        awardDaoService.delete(teamId, productId);
    }

    @Override
    public List<AwardProductListRes> getAwardProductList(Long teamId) {
        return awardDaoService.getAwardProductList(teamId);
    }

    /**
     * 抽奖
     * 校验积分是否满足抽奖条件、生成我的奖品、积分扣减、生成积分扣减日志、生成抽奖记录
     */
    @Override
    public Result<PrizeDrawRes> prizeDraw(BaseReq req, UserVO user) {
        // 校验积分是否满足抽奖条件
        Card card = cardDaoService.selectOneById(req.getTeamId(), req.getCardId());
        if (card == null) {
            return Result.fail(BaseCode.DATA_NOT_EXIST);
        }
        PointPrizeDrawSetting setting = pointPrizeDrawSettingDaoService.getOneByTeamId(req.getTeamId());
        if (setting.getSpendPoint() > card.getRemainPoint()) {
            return Result.fail(BaseCode.POINT_NOT_ENOUGH);
        }
        card.setRemainPoint(card.getRemainPoint() - setting.getSpendPoint());

        // 抽奖
        List<AwardProductListRes> productList = awardDaoService.getAwardProductList(req.getTeamId());
        int totalProbability = 0;
        List<AwardProductListRes> cumulativeProbabilities = new ArrayList<>();
        for (AwardProductListRes item : productList) {
            totalProbability += item.getRate();
            cumulativeProbabilities.add(item);
        }

        Random random = new Random();
        int randomNumber = random.nextInt(totalProbability) + 1;
        PrizeDrawRes res = null;
        for (AwardProductListRes item : cumulativeProbabilities) {
            if (randomNumber <= item.getRate()) {
                res = new PrizeDrawRes();
                res.setId(item.getId());
                res.setName(item.getName());
                res.setTeamId(item.getTeamId());
                break;
            }
            randomNumber -= item.getRate();
        }
        if (res == null) {
            return null;
        }

        // 抽奖记录
        PrizeDrawLog prizeDrawLog = PrizeDrawLog.builder().spendPoint(setting.getSpendPoint()).name(res.getName())
                .teamId(req.getTeamId()).cardId(req.getCardId()).creatorId(user.getId()).build();

        // 扣减的积分日志
        PointLog pointLog = new PointLog();
        pointLog.setPointType(PointTypeEnum.PRIZE_DRAW.getType());
        pointLog.setPoint(setting.getSpendPoint() * -1);
        pointLog.setEventName(PointTypeEnum.PRIZE_DRAW.getDesc());
        pointLog.setTeamId(req.getTeamId());
        pointLog.setCardId(req.getCardId());
        pointLog.setCreatorId(user.getId());
        pointLog.setUpdaterId(user.getId());
        pointLog.setDelFlag(DelFlagEnum.NORMAL.getType());

        awardDaoService.savePrizeDrawResult(card, prizeDrawLog, pointLog);
        return Result.ok(res);

    }

    @Override
    public Result<Long> updateLotteryRate(UpdateLotteryRateReq req) {

        return null;
    }

    @Override
    public Result<Long> savePrizeDrawResult(SavePrizeDrawResultReq req) {
        // 扣减个人总积分
        Card card = cardDaoService.selectOneById(req.getTeamId(), req.getCardId());
        if (card == null) {
            return Result.fail(BaseCode.DATA_NOT_EXIST);
        }
        if (req.getSpendPoint().compareTo(card.getRemainPoint()) > 0) {
            return Result.fail(BaseCode.POINT_NOT_ENOUGH);
        }
        card.setRemainPoint(card.getRemainPoint() - req.getSpendPoint());

        // 抽奖记录
        PrizeDrawLog prizeDrawLog = PrizeDrawLog.builder().spendPoint(req.getSpendPoint()).name(req.getName())
                .teamId(req.getTeamId()).cardId(req.getCardId()).creatorId(req.getUpdaterId()).build();

        // 扣减的积分日志
        PointLog pointLog = new PointLog();
        pointLog.setPointType(PointTypeEnum.PRIZE_DRAW.getType());
        pointLog.setPoint(req.getSpendPoint() * -1);
        pointLog.setEventName(PointTypeEnum.PRIZE_DRAW.getDesc() + "：" + req.getName());
        pointLog.setTeamId(req.getTeamId());
        pointLog.setCardId(req.getCardId());
        pointLog.setCreatorId(req.getUpdaterId());
        pointLog.setUpdaterId(req.getUpdaterId());
        pointLog.setDelFlag(DelFlagEnum.NORMAL.getType());

        awardDaoService.savePrizeDrawResult(card, prizeDrawLog, pointLog);
        return Result.ok(prizeDrawLog.getId());
    }

    @Override
    public Result<List<PrizeDrawLog>> myAwardList(MyAwardPageListReq req) {
        List<PrizeDrawLog> list = prizeDrawLogMapper.getMyAwardlist(req);
        return Result.ok(list);
    }

}
